use std::{io::{self, Write}, rc::Rc, cell::RefCell};

use crate::{native, rtda::Frame};

pub fn init() {
    // native::register("java/io/FileOutputStream", "initIDs", "()V", init_ids);
    native::register("java/io/FileOutputStream", "writeBytes", "([BIIZ)V", write_bytes);
}

// private static native void initIDs();
// ()V
fn init_ids(frame: Rc<RefCell<Frame>>) {
    // do nothing
}

// private native void writeBytes(byte b[], int off, int len, boolean append) throws IOException;
// ([BIIZ)V
fn write_bytes(frame:Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    // let this = vars.borrow().get_ref(0);
    let b = vars.borrow().get_ref(1).unwrap();
    let off = vars.borrow().get_int(2) as usize;
    let len = vars.borrow().get_int(3) as usize;
    // let append = vars.borrow().get_boolean(4);

    let j_bytes = unsafe { &*b }.get_array().get_bytes();
    let rs_bytes = cast_i8s_to_u8s(j_bytes);
    let rs_bytes = &rs_bytes[off..off+len];
    let mut stdout = io::stdout();  
    let _ = stdout.write_all(rs_bytes);
    // if let crate::rtda::heap::ArrayObject::Byte(j_bytes) = unsafe { &*b }.get_array().get_bytes() {
    //     let rs_bytes = cast_i8s_to_u8s(j_bytes);
    //     let rs_bytes = &rs_bytes[off..off+len];
    //     let mut stdout = io::stdout();  
    //     let _ = stdout.write_all(rs_bytes);
    // } else {
    //     panic!("type is not ArrayObject::Byte")
    // }
}

fn cast_i8s_to_u8s(i8s: &Vec<i8>) -> Vec<u8> {
    i8s.iter().map(|i| *i as u8).collect()
}